/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.cmp.arena;

import com.cmp.player.PlayerFactory;
import com.cmp.player.controls.CollisionControl;
import com.cmp.player.controls.InputControl;
import com.jme3.app.Application;
import com.jme3.app.SimpleApplication;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.collision.PhysicsCollisionEvent;
import com.jme3.bullet.collision.PhysicsCollisionListener;
import com.jme3.bullet.control.PhysicsControl;
import com.jme3.scene.Node;
import com.jme3.scene.control.Control;
import java.util.ArrayList;

/**
 * Contains the Map Node for the scene
 * and general game rules like scores, spawning and end of game.
 * @author krummer
 */
public class Arena extends AbstractAppState {
    
    private Node mapNode;
    private ArrayList<Node> playersList;
    private Node goalOne, goalTwo;
    
    private BulletAppState physicsState;
    private SimpleApplication app;
    
    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
        this.app = (SimpleApplication) app;
        this.playersList = new ArrayList<Node>();
        
        this.mapNode = new Node();
        this.goalOne = new Node();
        this.goalTwo = new Node();
        this.physicsState = app.getStateManager().getState(BulletAppState.class);
        
        //enable physics
        this.physicsState.getPhysicsSpace()
                .addCollisionListener(new PhysicsCollisionListener() {

            public void collision(PhysicsCollisionEvent event) {
                CollisionControl a = 
                        event.getNodeA().getControl(CollisionControl.class);
                CollisionControl b = 
                        event.getNodeB().getControl(CollisionControl.class);
                if(a != null) {
                    a.onCollision(event, event.getNodeB(), true);
                }
                if(b != null) {
                    b.onCollision(event, event.getNodeA(), false);
                }
            }
        });
    }
    
    public void loadMap() {
        //load map
        MapFactory.makeMap(this.mapNode, this.physicsState.getPhysicsSpace()
                , app.getAssetManager());
        
        //TODO:  remove test AI players.
        Node aiDude = new Node("AI");
        PlayerFactory.makePlayer(aiDude, false, PlayerFactory.Role.CARRIER, true, this.app.getAssetManager());
        this.addNode(aiDude);
        
        //spawn the players.
        for(Node player : this.playersList) {
            boolean team = player.getUserData("Team");
            
            if(team) {
                player.setLocalTranslation(goalOne.getLocalTranslation());
            } else {
                player.setLocalTranslation(goalTwo.getLocalTranslation());
            }
        }
    }
   
    
    @Override
    public void stateAttached(AppStateManager stateManager) {
        super.stateAttached(stateManager);
        stateManager.attach(new Announcer());
    }
    
    @Override
    public void stateDetached(AppStateManager stateManager) {
        super.stateAttached(stateManager);
        stateManager.detach(stateManager.getState(Announcer.class));
    }
    
    @Override
    public void cleanup() {
        super.cleanup();
        this.app.getStateManager().getState(Announcer.class).cleanup();
    }
    
    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        //cascade related app states
        this.app.getStateManager().getState(Announcer.class).setEnabled(enabled);
        
        if(enabled) {
            app.getRootNode().attachChild(this.mapNode);
        } else {
            app.getRootNode().detachChild(this.mapNode);
        }
    }
        
    public Node getMapNode(){
        return this.mapNode;
    }
    
    /**
     * 
     * @return a list that has all players attached.
     */
    public ArrayList<Node> getPlayersList() {
        return this.playersList;
    }

    /**
     * Allows you to replace the entire map.
     */
    public void setMapNode(Node mapNode){
        this.mapNode = mapNode;
    }
    
    public void addBullet(Node node) {
        this.getMapNode().attachChild(node);
     
        for(int i = 0; i < node.getNumControls(); i++) {
            Control control = node.getControl(i);
            if(control instanceof PhysicsControl){
                this.physicsState.getPhysicsSpace().add((PhysicsControl)control);
            }
        }
    }
    
    public void addNode(Node node) {
        if(node.getUserData("isPlayer") != null) {
            this.playersList.add(node);
        } else if(node.getUserData("isGoal") != null) {
            boolean team = node.getUserData("Team");
            if(team) {
                this.goalOne = node;
            } else {
                this.goalTwo = node;
            }
        }
        
        this.getMapNode().attachChild(node);
     
        for(int i = 0; i < node.getNumControls(); i++) {
            Control control = node.getControl(i);
            if(control instanceof PhysicsControl){
                this.physicsState.getPhysicsSpace().add((PhysicsControl)control);
            }
        }
    }
}
